package com.liuhuanss.idCard.service;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.liuhuanss.idCard.config.XfyunConfig;
import com.liuhuanss.idCard.pojo.dto.IdCardRecognitionResponse;
import com.liuhuanss.idCard.pojo.dto.ResponseData;
import com.liuhuanss.idCard.util.HttpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class IdCardService {
    @Autowired
    private XfyunConfig xfyunConfig;

    private static final Gson json = new Gson();

    public ResponseData recognizeIdCard(MultipartFile file) throws Exception {
        String url = assembleRequestUrl(
                xfyunConfig.getRequestUrl(),
                xfyunConfig.getApiKey(),
                xfyunConfig.getApiSecret()
        );

        String originalFilename = file.getOriginalFilename();
        String fileExtension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        }
        byte[] fileBytes = file.getBytes();
        String imageBase64 = Base64.getEncoder().encodeToString(fileBytes);

        // 构建请求参数
        String bodyParam = buildRequestParam(imageBase64, fileExtension);
        return handleRecognitionResult(url, bodyParam);
    }

    private String buildRequestParam(String imageBase64, String imageEncoding) {
        JsonObject jso = new JsonObject();

        // Header
        JsonObject header = new JsonObject();
        header.addProperty("app_id", xfyunConfig.getAppid());
        header.addProperty("status", 3);
        jso.add("header", header);

        // Parameter
        JsonObject parameter = new JsonObject();
        JsonObject service = new JsonObject();
        JsonObject result = new JsonObject();
        result.addProperty("encoding", "utf8");
        result.addProperty("format", "json");
        result.addProperty("compress", "raw");
        service.add("result", result);
        service.addProperty("template_list", "id_card");
        parameter.add("s5ccecfce", service);
        jso.add("parameter", parameter);

        // Payload
        JsonObject payload = new JsonObject();
        JsonObject inputImage = new JsonObject();
        inputImage.addProperty("encoding", imageEncoding);
        inputImage.addProperty("status", 3);
        inputImage.addProperty("image", imageBase64);
        payload.add("s5ccecfce_data_1", inputImage);
        jso.add("payload", payload);

        return jso.toString();
    }

    private ResponseData handleRecognitionResult(String url, String bodyParam) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-type", "application/json");
        String result = HttpUtil.doPost2(url, headers, bodyParam);
        if (result != null) {
            return json.fromJson(result, ResponseData.class);
        }
        return null;
    }

    public String assembleRequestUrl(String requestUrl, String apiKey, String apiSecret) {
        try {
            String httpRequestUrl = requestUrl
                    .replace("ws://", "http://")
                    .replace("wss://", "https://");

            URL url = new URL(httpRequestUrl);
            SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
            format.setTimeZone(TimeZone.getTimeZone("GMT"));
            String date = format.format(new Date());

            String host = url.getHost();
            StringBuilder builder = new StringBuilder("host: ")
                    .append(host).append("\n")
                    .append("date: ").append(date).append("\n")
                    .append("POST ").append(url.getPath()).append(" HTTP/1.1");

            Mac mac = Mac.getInstance("hmacsha256");
            SecretKeySpec spec = new SecretKeySpec(
                    apiSecret.getBytes(StandardCharsets.UTF_8),
                    "hmacsha256"
            );
            mac.init(spec);
            byte[] hexDigits = mac.doFinal(builder.toString().getBytes(StandardCharsets.UTF_8));
            String sha = Base64.getEncoder().encodeToString(hexDigits);

            String authorization = String.format(
                    "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"",
                    apiKey, "hmac-sha256", "host date request-line", sha
            );
            String authBase = Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8));

            return String.format("%s?authorization=%s&host=%s&date=%s",
                    requestUrl,
                    URLEncoder.encode(authBase, String.valueOf(StandardCharsets.UTF_8)),
                    URLEncoder.encode(host, String.valueOf(StandardCharsets.UTF_8)),
                    URLEncoder.encode(date, String.valueOf(StandardCharsets.UTF_8))
            );
        } catch (Exception e) {
            throw new RuntimeException("Failed to assemble request URL", e);
        }
    }
}
